# -*- Mode: Python -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

name = 'DOM'

# A quick warning:
#
# Attributes or methods that call GetCurrentNativeCallContext must not be
# quick-stubbed, because quick stubs don't generate a native call context.
# qsgen.py has no way of knowing which attributes and methods do this, as it
# looks at interfaces, not implementations.  The symptoms, if you quick-stub
# one of those, can be really weird, because GetCurrentNativeCallContext
# doesn't crash--it may in fact return a plausible wrong answer.

members = [ 
    # dom/interfaces/base
    #
    # Note that many implementations of interfaces in this directory
    # use GetCurrentNativeCallContext, notably:
    #   - nsIDOMCrypto.{generateCRMFRequest,signText}
    #   - nsIDOMLocation.reload
    #   - nsIDOMNSHistory.go
    #   - nsIDOMJSPluginArray.refresh
    #   - nsIDOMWindow.postMessage
    #   - nsIDOMJSWindow.{prompt,setTimeout,setInterval,open,openDialog}
    #
    # (And nsIDOMModalContentWindow.returnValue is an attribute of type
    # nsIVariant, which qsgen.py can't handle.)
    #
    'nsIDOMWindow.name',
    'nsIDOMWindow.parent',
    'nsIDOMWindow.top',
    'nsIDOMWindow.self',
    # Several window properties are magically resolved, including
    # location, _content, navigator, document, and window itself.
    # These do not need quick stubs.
    #'nsIDOMWindow.document',
    'nsIDOMWindow.getSelection',
    'nsIDOMWindow.scrollByLines',
    'nsIDOMWindow.getComputedStyle',
    'nsIDOMWindow.sessionStorage',
    'nsIDOMWindow.localStorage',
    'nsIDOMWindow.onmouseenter',
    'nsIDOMWindow.onmouseleave',
    'nsIDOMJSWindow.dump',
    'nsIDOMScreen.top',
    'nsIDOMScreen.height',
    'nsIDOMScreen.width',
    'nsIDOMScreen.left',
    'nsIDOMClientRect.*',
    'nsIDOMPaintRequest.*',
    # nsLocationSH has ~ALLOW_PROP_MODS_TO_PROTOTYPE, so don't try.
    #'nsIDOMLocation.hostname',
    #'nsIDOMLocation.href',

    # dom/interfaces/canvas
    #
    # nsIDOMCanvasRenderingContext2D and friends
    'nsIDOMCanvasRenderingContext2D.*',
    'nsIDOMTextMetrics.*',
    'nsIDOMCanvasGradient.*',
    'nsIDOMCanvasPattern.*',
    'nsIDOMImageData.*',

    # dom/interfaces/core
    'nsIDOMCharacterData.data',
    'nsIDOMCharacterData.length',
    'nsIDOMDocument.documentElement',
    'nsIDOMDocument.implementation',
    'nsIDOMDocument.getElementsByTagName',
    'nsIDOMDocument.doctype',
    'nsIDOMDocument.getElementsByTagNameNS',
    'nsIDOMDocument.getElementById',
    'nsIDOMDocument.createDocumentFragment',
    'nsIDOMDocument.createElement',
    'nsIDOMDocument.createElementNS',
    'nsIDOMDocument.importNode',
    'nsIDOMDocument.createTextNode',
    'nsIDOMDocument.documentURI',
    'nsIDOMDocument.adoptNode',
    'nsIDOMDocument.defaultView',
    'nsIDOMDocument.createNodeIterator',
    'nsIDOMDocument.createEvent',
    'nsIDOMDocument.getElementsByClassName',
    'nsIDOMDocument.title',
    'nsIDOMDocument.referrer',
    'nsIDOMDocument.hasFocus',
    # This property is treated specially in nsDOMClassInfo in a way that
    # would shadow any quick stub.  Also, document.location is a special
    # case for security.
    #'nsIDOMDocument.location',
    'nsIDOMDocument.elementFromPoint',
    'nsIDOMDocument.activeElement',
    'nsIDOMDocument.onreadystatechange',
    'nsIDOMDocument.onmouseenter',
    'nsIDOMDocument.onmouseleave',
    'nsIDOMElement.removeAttributeNS',
    'nsIDOMElement.removeAttribute',
    'nsIDOMElement.getAttribute',
    'nsIDOMElement.getElementsByTagName',
    'nsIDOMElement.setAttribute',
    'nsIDOMElement.getElementsByTagNameNS',
    'nsIDOMElement.hasAttributeNS',
    'nsIDOMElement.tagName',
    'nsIDOMElement.setAttributeNS',
    'nsIDOMElement.hasAttribute',
    'nsIDOMElement.getAttributeNS',
    'nsIDOMElement.onmouseenter',
    'nsIDOMElement.onmouseleave',
    'nsIDOMElement.getElementsByClassName',
    'nsIDOMElement.getClientRects',
    'nsIDOMElement.getBoundingClientRect',
    'nsIDOMElement.scrollTop',
    'nsIDOMElement.scrollLeft',
    'nsIDOMElement.scrollHeight',
    'nsIDOMElement.scrollWidth',
    'nsIDOMElement.clientTop',
    'nsIDOMElement.clientLeft',
    'nsIDOMElement.clientHeight',
    'nsIDOMElement.clientWidth',
    'nsIDOMElement.firstElementChild',
    'nsIDOMElement.lastElementChild',
    'nsIDOMElement.previousElementSibling',
    'nsIDOMElement.nextElementSibling',
    'nsIDOMElement.childElementCount',
    'nsIDOMElement.children',
    'nsIDOMElement.classList',
    'nsIDOMElement.setCapture',
    'nsIDOMElement.releaseCapture',
    'nsIDOMElement.mozMatchesSelector',
    'nsIDOMNamedNodeMap.item',
    'nsIDOMNamedNodeMap.length',
    'nsIDOMNode.*',
    'nsIDOMNodeSelector.querySelector',
    'nsIDOMNodeSelector.querySelectorAll',
    'nsIDOMText.splitText',
    'nsIDOMDOMImplementation.*',
    'nsIDOMDOMStringList.*',
    'nsIDOMXULDocument.getBoxObjectFor',
    'nsIDOMMutationRecord.*',

    # dom/interfaces/css
    'nsIDOMElementCSSInlineStyle.*',
    'nsIDOMCSS2Properties.*',
    'nsIDOMRect.*',
    'nsIDOMCSSStyleDeclaration.*',

    # dom/interfaces/events
    'nsIDOMEventTarget.addEventListener',
    'nsIDOMEventTarget.removeEventListener',
    'nsIDOMEventTarget.dispatchEvent',

    'nsIDOMEvent.type',
    'nsIDOMEvent.target',
    'nsIDOMEvent.currentTarget',
    'nsIDOMEvent.eventPhase',
    'nsIDOMEvent.bubbles',
    'nsIDOMEvent.cancelable',
    'nsIDOMEvent.timeStamp',
    'nsIDOMEvent.stopPropagation',
    'nsIDOMEvent.preventDefault',
    'nsIDOMEvent.initEvent',
    'nsIDOMEvent.defaultPrevented',
    'nsIDOMEvent.stopImmediatePropagation',
    'nsIDOMMouseEvent.*',
    'nsIDOMKeyEvent.*',
    'nsIDOMMutationEvent.*',
    'nsIDOMDragEvent.*',
    'nsIDOMScrollAreaEvent.*',
    'nsIDOMNotifyPaintEvent.*',
    'nsIDOMMessageEvent.*',
    'nsIDOMMouseScrollEvent.*',
    'nsIDOMProgressEvent.lengthComputable',
    'nsIDOMProgressEvent.loaded',
    'nsIDOMProgressEvent.total',
    #XXX Can't quickstub initProgressEvent because it has long long parameters.
    'nsIDOMNSEvent.originalTarget',
    'nsIDOMNSEvent.getPreventDefault',
    'nsIDOMUIEvent.which',
    'nsIDOMUIEvent.rangeParent',
    'nsIDOMUIEvent.rangeOffset',
    'nsIDOMUIEvent.pageX',
    'nsIDOMUIEvent.pageY',
    'nsIDOMUIEvent.isChar',

    'nsIDOMTouch.*',
    'nsIDOMTouchEvent.*',

    # dom/interfaces/geolocation - None.

    # dom/interfaces/html
    'nsIDOMHTMLAnchorElement.href',
    'nsIDOMHTMLAnchorElement.rel',
    'nsIDOMHTMLAnchorElement.target',
    'nsIDOMHTMLAnchorElement.name',
    'nsIDOMHTMLAnchorElement.text',
    'nsIDOMHTMLAnchorElement.search',
    'nsIDOMHTMLAnchorElement.hash',
    'nsIDOMHTMLBaseElement.href',
    'nsIDOMHTMLBaseElement.target',
    'nsIDOMHTMLButtonElement.name',
    'nsIDOMHTMLButtonElement.form',
    'nsIDOMHTMLButtonElement.value',
    'nsIDOMHTMLButtonElement.disabled',
    'nsIDOMHTMLCommandElement.*',
    'nsIDOMHTMLDocument.body',
    'nsIDOMHTMLDocument.getElementsByName',
    'nsIDOMHTMLDocument.anchors',
    'nsIDOMHTMLDocument.links',
    'nsIDOMHTMLDocument.URL',
    'nsIDOMHTMLDocument.forms',
    'nsIDOMHTMLDocument.cookie',
    'nsIDOMHTMLDocument.images',
    'nsIDOMHTMLDocument.write',
    'nsIDOMHTMLDocument.writeln',
    'nsIDOMHTMLDocument.domain',
    'nsIDOMHTMLDocument.getSelection',
    'nsIDOMHTMLDocument.designMode',
    'nsIDOMHTMLDocument.head',
    # We can't quick stub nsIDOMHTMLElement.* because we don't 
    # generate quick stubs for nsIVariant attributes.
    'nsIDOMHTMLElement.id',
    'nsIDOMHTMLElement.title',
    'nsIDOMHTMLElement.lang',
    'nsIDOMHTMLElement.dir',
    'nsIDOMHTMLElement.className',
    'nsIDOMHTMLElement.dataset',
    'nsIDOMHTMLElement.itemScope',
    'nsIDOMHTMLElement.itemId',
    'nsIDOMHTMLElement.properties',
    'nsIDOMHTMLElement.hidden',
    'nsIDOMHTMLElement.tabIndex',
    'nsIDOMHTMLElement.accessKey',
    'nsIDOMHTMLElement.accessKeyLabel',
    'nsIDOMHTMLElement.draggable',
    'nsIDOMHTMLElement.contentEditable',
    'nsIDOMHTMLElement.isContentEditable',
    'nsIDOMHTMLElement.contextMenu',
    'nsIDOMHTMLElement.spellcheck',
    'nsIDOMHTMLElement.innerHTML',
    'nsIDOMHTMLElement.outerHTML',
    'nsIDOMHTMLElement.offsetParent',
    'nsIDOMHTMLElement.offsetTop',
    'nsIDOMHTMLElement.offsetLeft',
    'nsIDOMHTMLElement.offsetWidth',
    'nsIDOMHTMLElement.offsetHeight',
    'nsIDOMHTMLFormElement.elements',
    'nsIDOMHTMLFormElement.name',
    'nsIDOMHTMLFormElement.submit',
    'nsIDOMHTMLFormElement.length',
    'nsIDOMHTMLFormElement.target',
    'nsIDOMHTMLFormElement.action',
    'nsIDOMHTMLFrameElement.src',
    'nsIDOMHTMLFrameElement.contentDocument',
    'nsIDOMHTMLFrameElement.contentWindow',
    'nsIDOMHTMLFrameElement.name',
    'nsIDOMHTMLFrameSetElement.rows',
    'nsIDOMHTMLFrameSetElement.cols',
    'nsIDOMHTMLIFrameElement.src',
    'nsIDOMHTMLIFrameElement.contentDocument',
    'nsIDOMHTMLIFrameElement.contentWindow',
    'nsIDOMHTMLImageElement.src',
    'nsIDOMHTMLImageElement.name',
    'nsIDOMHTMLImageElement.height',
    'nsIDOMHTMLImageElement.width',
    'nsIDOMHTMLImageElement.complete',
    'nsIDOMHTMLInputElement.defaultChecked',
    'nsIDOMHTMLInputElement.disabled',
    'nsIDOMHTMLInputElement.select',
    'nsIDOMHTMLInputElement.checked',
    'nsIDOMHTMLInputElement.type',
    'nsIDOMHTMLInputElement.form',
    'nsIDOMHTMLInputElement.src',
    'nsIDOMHTMLInputElement.name',
    'nsIDOMHTMLInputElement.value',
    'nsIDOMHTMLInputElement.files',
    'nsIDOMHTMLInputElement.textLength',
    'nsIDOMHTMLInputElement.selectionStart',
    'nsIDOMHTMLInputElement.selectionEnd',
    'nsIDOMHTMLInputElement.selectionDirection',
    'nsIDOMHTMLInputElement.setSelectionRange',
    'nsIDOMHTMLLinkElement.disabled',
    'nsIDOMHTMLMeterElement.*',
    'nsIDOMHTMLMenuElement.*',
    'nsIDOMHTMLMenuItemElement.*',
    'nsIDOMHTMLOptionElement.index',
    'nsIDOMHTMLOptionElement.selected',
    'nsIDOMHTMLOptionElement.form',
    'nsIDOMHTMLOptionElement.text',
    'nsIDOMHTMLOptionElement.defaultSelected',
    'nsIDOMHTMLOptionElement.value',
    'nsIDOMHTMLOptionElement.label',
    'nsIDOMHTMLOptionElement.disabled',
    'nsIDOMHTMLProgressElement.*',
    'nsIDOMHTMLSelectElement.name',
    'nsIDOMHTMLSelectElement.form',
    'nsIDOMHTMLSelectElement.add',
    'nsIDOMHTMLSelectElement.value',
    'nsIDOMHTMLSelectElement.disabled',
    'nsIDOMHTMLSelectElement.length',
    'nsIDOMHTMLSelectElement.remove',
    'nsIDOMHTMLSelectElement.selectedIndex',
    'nsIDOMHTMLSelectElement.item',
    'nsIDOMHTMLSelectElement.type',
    'nsIDOMHTMLSelectElement.options',
    'nsIDOMHTMLSelectElement.size',
    'nsIDOMHTMLStyleElement.disabled',
    'nsIDOMHTMLTableCellElement.colSpan',
    'nsIDOMHTMLTableCellElement.headers',
    'nsIDOMHTMLTableCellElement.cellIndex',
    'nsIDOMHTMLTableCellElement.rowSpan',
    'nsIDOMHTMLTableCellElement.abbr',
    'nsIDOMHTMLTableCellElement.scope',
    'nsIDOMHTMLTableCellElement.noWrap',
    'nsIDOMHTMLTableCellElement.width',
    'nsIDOMHTMLTableColElement.span',
    'nsIDOMHTMLTableColElement.width',
    'nsIDOMHTMLTableElement.rows',
    'nsIDOMHTMLTableElement.deleteRow',
    'nsIDOMHTMLTableElement.summary',
    'nsIDOMHTMLTableElement.insertRow',
    'nsIDOMHTMLTableRowElement.sectionRowIndex',
    'nsIDOMHTMLTableRowElement.rowIndex',
    'nsIDOMHTMLTableRowElement.cells',
    'nsIDOMHTMLTableRowElement.deleteCell',
    'nsIDOMHTMLTableRowElement.insertCell',
    'nsIDOMHTMLTableSectionElement.rows',
    'nsIDOMHTMLTableSectionElement.insertRow',
    'nsIDOMHTMLTableSectionElement.deleteRow',
    'nsIDOMHTMLTextAreaElement.rows',
    'nsIDOMHTMLTextAreaElement.name',
    'nsIDOMHTMLTextAreaElement.form',
    'nsIDOMHTMLTextAreaElement.defaultValue',
    'nsIDOMHTMLTextAreaElement.cols',
    'nsIDOMHTMLTextAreaElement.value',
    'nsIDOMHTMLTextAreaElement.type',
    'nsIDOMHTMLTextAreaElement.select',
    'nsIDOMHTMLTextAreaElement.setSelectionRange',
    'nsIDOMHTMLTextAreaElement.selectionStart',
    'nsIDOMHTMLTextAreaElement.selectionEnd',
    'nsIDOMHTMLTextAreaElement.selectionDirection',
    'nsIDOMHTMLTextAreaElement.textLength',
    'nsIDOMHTMLTextAreaElement.wrap',
    'nsIDOMHTMLTitleElement.text',
    'nsIDOMHTMLCanvasElement.width',
    'nsIDOMHTMLCanvasElement.height',
    'nsIDOMHTMLCanvasElement.getContext',
    'nsIDOMHTMLCanvasElement.toDataURL',

    # dom/interfaces/json - None.
    # All methods of nsIJSON call GetCurrentNativeCallContext.

    # dom/interfaces/load-save - None.

    # dom/interfaces/offline - None.

    # dom/interfaces/range
    'nsIDOMRange.*',

    # dom/interfaces/sidebar - None.

    # dom/interfaces/smil - None.

    # dom/interfaces/storage
    'nsIDOMToString.toString',
    'nsIDOMStorage.setItem',
    'nsIDOMStorage.length',
    'nsIDOMStorage.getItem',
    'nsIDOMStorage.key',
    'nsIDOMStorage.removeItem',
    'nsIDOMStorage.clear',
    'nsIDOMStorageItem.value',

    # dom/interfaces/stylesheets - None.

    # dom/interfaces/svg - None.
    'nsIDOMSVGStylable.*',

    # dom/interfaces/traversal
    'nsIDOMNodeIterator.nextNode',

    # dom/interfaces/xbl - None.

    # dom/interfaces/xpath
    'nsIDOMXPathEvaluator.evaluate',
    'nsIDOMXPathEvaluator.createExpression',
    'nsIDOMXPathEvaluator.createNSResolver',
    'nsIDOMXPathExpression.evaluate',
    'nsIDOMXPathNSResolver.lookupNamespaceURI',
    'nsIDOMXPathResult.snapshotItem',
    'nsIDOMXPathResult.iterateNext',
    'nsIDOMXPathResult.snapshotLength',
    'nsIDOMXPathResult.resultType',
    'nsIDOMXPathResult.numberValue',
    'nsIDOMXPathResult.stringValue',
    'nsIDOMXPathResult.booleanValue',
    'nsIDOMXPathResult.singleNodeValue',
    'nsIDOMNSXPathExpression.evaluateWithContext',

    # dom/interfaces/xul
    'nsIDOMXULElement.*',

    # layout/xul/base/public
    'nsIBoxObject.x',
    'nsIBoxObject.y',
    'nsIBoxObject.screenX',
    'nsIBoxObject.screenY',
    'nsIBoxObject.width',
    'nsIBoxObject.height',

    # FileReader
    'nsIDOMFileReader.*',
    
    # XHR
    'nsIXMLHttpRequest.*',
    # nsIXMLHttpRequest.channel is not used on the web, and more
    # importantly relies on the CAPS check that quickstubs don't make.
    '-nsIXMLHttpRequest.channel',
    # various XHR things use ACString and AUTF8String and [cstring]
    # which quickstubs don't handle as return values (or at all in the
    # case of AUTF8String) yet.
    '-nsIXMLHttpRequest.statusText',
    '-nsIXMLHttpRequest.getAllResponseHeaders',
    '-nsIXMLHttpRequest.getResponseHeader',
    '-nsIXMLHttpRequest.setRequestHeader',
    '-nsIXMLHttpRequest.overrideMimeType',
    # nsIXMLHttpRequestUpload doesn't live in its own IDL file, so
    # can't be quickstubbed
    '-nsIXMLHttpRequest.upload',

    # WebSocket
    'nsIWebSocket.*',

    # webgl
    'nsIDOMWebGLRenderingContext.*',
    # getContextAttributes is directly manipulating its return value
    '-nsIDOMWebGLRenderingContext.getContextAttributes',

    # Audio
    'nsIDOMNotifyAudioAvailableEvent.frameBuffer',
    'nsIDOMNotifyAudioAvailableEvent.time',
    'nsIDOMHTMLAudioElement.mozWriteAudio',

    # dom/indexedDB
    'nsIIDBCursor.*',
    'nsIIDBCursorWithValue.*',
    'nsIIDBDatabase.*',
    'nsIIDBFactory.*',
    'nsIIDBFileHandle.*',
    'nsIIDBIndex.*',
    'nsIIDBKeyRange.*',
    'nsIIDBObjectStore.*',
    'nsIIDBRequest.*',
    'nsIIDBTransaction.*',
    'nsIIDBOpenDBRequest.*',
    'nsIIDBVersionChangeEvent.*',
    'nsIIndexedDatabaseUsageCallback.*',
    'nsIIndexedDatabaseManager.*',

    'nsIDOMDOMError.*',

    # dom/file
    'nsIDOMFileHandle.*',
    '-nsIDOMFileHandle.getFileId',
    '-nsIDOMFileHandle.getFileInfo',
    'nsIDOMFileRequest.*',
    'nsIDOMLockedFile.*',
    ]

# Most interfaces can be found by searching the includePath; to find
# nsIDOMEvent, for example, just look for nsIDOMEvent.idl.  But IDL filenames
# for very long interface names are slightly abbreviated, and many interfaces
# don't have their own files, just for extra wackiness.  So qsgen.py needs
# a little help.
#
irregularFilenames = {
    # abbreviations
    'nsIDOMHTMLTableSectionElement': 'nsIDOMHTMLTableSectionElem',

    # stowaways
    'nsIDOMTextMetrics': 'nsIDOMCanvasRenderingContext2D',
    'nsIDOMCanvasGradient': 'nsIDOMCanvasRenderingContext2D',
    'nsIDOMCanvasPattern': 'nsIDOMCanvasRenderingContext2D',
    'nsIDOMImageData': 'nsIDOMCanvasRenderingContext2D',

    'nsIDOMBlob': 'nsIDOMFile',

    'nsIWebGLTexture': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLBuffer': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLProgram': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLShader': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLShaderArray': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLFramebuffer': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLRenderbuffer': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLShaderPrecisionFormat' : 'nsIDOMWebGLRenderingContext',
    'nsIWebGLActiveInfo': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLUniformLocation': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLExtension': 'nsIDOMWebGLRenderingContext',
    'nsIWebGLExtensionStandardDerivatives' : 'nsIDOMWebGLRenderingContext',
    'nsIWebGLExtensionTextureFilterAnisotropic' : 'nsIDOMWebGLRenderingContext',
    'nsIWebGLExtensionLoseContext' : 'nsIDOMWebGLRenderingContext',
    'nsIWebGLExtensionCompressedTextureS3TC' : 'nsIDOMWebGLRenderingContext',

    'nsIIndexedDatabaseUsageCallback': 'nsIIndexedDatabaseManager',

    'nsIDOMTouch': 'nsIDOMTouchEvent',
    'nsIDOMTouchList': 'nsIDOMTouchEvent',

    'nsIDOMMutationRecord': 'nsIDOMMutationObserver',

    'nsITelephoneCallback': 'nsITelephone',
    }

customIncludes = [
    'nsINode.h',
    'nsIContent.h',
    'nsIDocument.h',
    'nsCSSPropertiesQS.h',
    'nsDocument.h',
    'nsDOMTokenList.h',
    'nsGenericDOMDataNode.h',
    'nsGenericElement.h',
    'nsGenericHTMLElement.h',
    'nsSVGStylableElement.h',
    'nsHTMLDocument.h',
    'nsDOMQS.h',
    'mozilla/dom/ImageData.h'
    ]

customQuickStubs = [
    'CustomQS_WebGL.h',
    'CustomQS_Canvas2D.h'
    ]

customReturnInterfaces = [
    'nsIDOMCanvasPattern',
    'nsIDOMCanvasGradient',
    'nsIDOMImageData'
    ]

nsIDOMNode_GetChildNodes_customMethodCallCode = """
    nsChildContentList* result = static_cast<nsChildContentList*>(self->GetChildNodesList());
    rv = result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
"""

nsIDOMHTMLDocument_Write_customMethodCallCode = """
    nsAString &str = arg0;
    for (unsigned i = 1; i < argc; ++i) {
      xpc_qsDOMString next_arg(cx, argv[i], &argv[i],
                               xpc_qsDOMString::eStringify,
                               xpc_qsDOMString::eStringify);
      if (!next_arg.IsValid())
        return JS_FALSE;

      str.Append(next_arg);
    }

    rv = self->%s(arg0, cx);
"""

nsIDOMStorage_Clear_customMethodCallCode = """
    rv = self->Clear();
    if (NS_SUCCEEDED(rv))
        JS_ClearScope(cx, obj);
"""

CUSTOM_QS = {
    'skipgen': True,
    'traceable': False
}

CUSTOM_QS_TN = {
    'skipgen': True,
    'traceable': True
}

customMethodCalls = {
    'nsIDOMNode_GetNextSibling': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetNextSibling();',
        'canFail': False
        },
    'nsIDOMNode_GetFirstChild': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetFirstChild();',
        'canFail': False
        },
    'nsIDOMNode_GetChildNodes': {
        'thisType': 'nsINode',
        'code': nsIDOMNode_GetChildNodes_customMethodCallCode
        },
    'nsIDOMNode_GetPreviousSibling': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetPreviousSibling();',
        'canFail': False
        },
    'nsIDOMNode_GetLastChild': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetLastChild();',
        'canFail': False
        },
    'nsIDOMNode_GetOwnerDocument': {
        'thisType': 'nsINode',
        'code': '    nsIDocument *result = self->GetOwnerDocument();',
        'canFail': False
        },
    'nsIDOMNode_GetParentNode': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetNodeParent();',
        'canFail': False
        },
    'nsIDOMNode_GetParentElement': {
        'thisType': 'nsINode',
        'code': '    nsINode *result = self->GetElementParent();',
        'canFail': False
        },
    'nsIDOMNode_InsertBefore': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'arg1Type': 'nsINode',
        'code': '    nsINode *result = self->InsertBefore(arg0, arg1, &rv);\n'
                '    if(NS_FAILED(rv))\n'
                '        result = nullptr;'
        },
    'nsIDOMNode_ReplaceChild': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'arg1Type': 'nsINode',
        'code': '    nsINode *result = self->ReplaceChild(arg0, arg1, &rv);\n'
                '    if(NS_FAILED(rv))\n'
                '        result = nullptr;'
        },
    'nsIDOMNode_RemoveChild': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'code': '    rv = self->RemoveChild(arg0);\n'
                '    nsINode *result = NS_SUCCEEDED(rv) ? arg0 : nullptr;'
        },
    'nsIDOMNode_AppendChild': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'code': '    nsINode *result = self->AppendChild(arg0, &rv);\n'
                '    if(NS_FAILED(rv))\n'
                '        result = nullptr;'
        },
    'nsIDOMNode_GetNodeType': {
        'thisType': 'nsINode',
        'code': 'PRUint16 result = self->NodeType();',
        'canFail': False
        },
    'nsIDOMNode_GetNodeName': {
        'thisType': 'nsINode',
        'code': 'nsString result = self->NodeName();',
        'canFail': False
        },
    'nsIDOMNode_GetLocalName': {
        'thisType': 'nsINode',
        'code': 'nsString result = self->LocalName();',
        'canFail': False
        },
    'nsIDOMHTMLDocument_': {
        'thisType': 'nsHTMLDocument'
        },
    'nsIDOMHTMLDocument_Write': {
        'thisType': 'nsHTMLDocument',
        'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Write'
        },
    'nsIDOMHTMLDocument_Writeln': {
        'thisType': 'nsHTMLDocument',
        'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Writeln'
        },
    'nsIDOMHTMLDocument_GetBody': {
        'thisType': 'nsHTMLDocument',
        'code': '    nsIContent *result = self->GetBody();',
        'canFail': False
        },
    'nsIDOMHTMLDocument_GetHead': {
        'thisType': 'nsHTMLDocument',
        'code': '    nsIContent *result = self->GetHead();',
        'canFail': False
        },
    'nsIDOMHTMLDocument_GetElementsByName': {
        'thisType': 'nsHTMLDocument',
        'code': '    nsRefPtr<nsContentList> result = '
                'self->GetElementsByName(arg0);',
        'canFail': False
        },
    'nsIDOMStorage_Clear': {
        'code': nsIDOMStorage_Clear_customMethodCallCode
        },
    'nsIDOMCanvasRenderingContext2D_StrokeStyle': { 'skipgen': True },
    'nsIDOMCanvasRenderingContext2D_StrokeStyle': { 'skipgen': True },
    'nsIDOMCanvasRenderingContext2D_FillStyle': { 'skipgen': True },
    'nsIDOMCanvasRenderingContext2D_FillStyle': { 'skipgen': True },
    'nsIDOMCSS2Properties_': {
        'thisType': 'nsICSSDeclaration',
        'additionalArguments': 'const nsCSSProperty prop',
        'additionalArgumentValues': 'QS_CSS_PROP_%s',
        'getter_code': '    nsString result;\n' + 
                       '    rv = self->GetPropertyValue(prop, result);',
        'setter_code': '    rv = self->SetPropertyValue(prop, arg0);',
        'canFail': True
        },
    'nsIDOMElement_GetScrollTop': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetScrollTop();',
        'canFail': False
        },
    'nsIDOMElement_SetScrollTop': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_GetScrollLeft': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetScrollLeft();',
        'canFail': False
        },
    'nsIDOMElement_SetScrollLeft': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_GetScrollHeight': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetScrollHeight();',
        'canFail': False
        },
    'nsIDOMElement_GetScrollWidth': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetScrollWidth();',
        'canFail': False
        },
    'nsIDOMElement_GetClientTop': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetClientTop();',
        'canFail': False
        },
    'nsIDOMElement_SetClientTop': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_GetClientLeft': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetClientLeft();',
        'canFail': False
        },
    'nsIDOMElement_SetClientLeft': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_GetClientHeight': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetClientHeight();',
        'canFail': False
        },
    'nsIDOMElement_GetClientWidth': {
        'thisType': 'nsGenericElement',
        'code': '    PRInt32 result = self->GetClientWidth();',
        'canFail': False
        },
    'nsIDOMElement_GetFirstElementChild': {
        'thisType': 'nsGenericElement',
        'code': '    nsIContent *result = self->GetFirstElementChild();',
        'canFail': False
        },
    'nsIDOMElement_GetLastElementChild': {
        'thisType': 'nsGenericElement',
        'code': '    nsIContent *result = self->GetLastElementChild();',
        'canFail': False
        },
    'nsIDOMElement_GetPreviousElementSibling': {
        'thisType': 'nsGenericElement',
        'code': '    nsIContent *result = self->GetPreviousElementSibling();',
        'canFail': False
        },
    'nsIDOMElement_GetNextElementSibling': {
        'thisType': 'nsGenericElement',
        'code': '    nsIContent *result = self->GetNextElementSibling();',
        'canFail': False
        },
    'nsIDOMElement_GetClassList': {
        'thisType': 'nsGenericElement',
        'code': '    nsDOMTokenList *result = self->GetClassList(&rv);'
        },
    'nsIDOMElement_SetCapture': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_ReleaseCapture': {
        'thisType': 'nsGenericElement',
        'canFail': False
        },
    'nsIDOMElement_MozMatchesSelector': {
        'thisType': 'nsGenericElement',
        'code': '    bool result = self->MozMatchesSelector(arg0, &rv);',
        },
    'nsIDOMNodeSelector_QuerySelector': {
        'thisType': 'nsINode',
        'code': '    nsIContent* result = '
                'nsGenericElement::doQuerySelector(self, arg0, &rv);'
        },
    'nsIDOMNodeSelector_QuerySelectorAll': {
        'thisType': 'nsINode',
        'code': '    nsCOMPtr<nsIDOMNodeList> result;\n'
                '    rv = nsGenericElement::doQuerySelectorAll(self, '
                'arg0, getter_AddRefs(result));'
        },
    'nsIDOMNode_Normalize': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_GetBaseURI': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_CompareDocumentPosition': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'code': '    PRUint16 result;\n'
                '    rv = self->CompareDocPosition(arg0, &result);',
        'canFail': True
        },
    'nsIDOMNode_GetTextContent': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_LookupPrefix': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_IsDefaultNamespace': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_LookupNamespaceURI': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_IsEqualNode': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'code': '    bool result = self->IsEqualTo(arg0);',
        'canFail': False
        },
    'nsIDOMNode_GetUserData': {
        'thisType': 'nsINode',
        'canFail': False
        },
    'nsIDOMNode_Contains': {
        'thisType': 'nsINode',
        'arg0Type': 'nsINode',
        'code': '    bool result = self->Contains(arg0);',
        'canFail': False
        },
    'nsIDOMHTMLElement_': {
        'thisType': 'nsGenericHTMLElement'
        },
    'nsIDOMElementCSSInlineStyle_GetStyle': {
        'thisType': 'nsStyledElement',
        'code': '    /* XXXbz MathML elements inherit from nsStyledElement but\n'
                '       don\'t actually implement GetStyle. */\n'
                '    if (self->GetNameSpaceID() == kNameSpaceID_MathML)\n'
                '      return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_CONVERT_JS);\n'
                '    nsIDOMCSSStyleDeclaration* result = '
                'self->GetStyle(&rv);'
        },
    'nsIDOMSVGStylable_GetStyle': {
        'thisType': 'nsSVGStylableElement',
        'code': '    nsIDOMCSSStyleDeclaration* result = '
                'self->GetStyle(&rv);'
        },
    'nsIDOMDocument_': {
        'thisType': 'nsDocument'
        },
    'nsIDOMDocument_GetElementById': {
        'thisType': 'nsDocument',
        'code': '    mozilla::dom::Element *result = self->GetElementById(arg0);',
        'canFail': False
        },
    'nsIDOMDocument_GetElementsByTagName': {
        'thisType': 'nsDocument',
        'code': '    nsRefPtr<nsContentList> result ='
                'self->GetElementsByTagName(arg0);',
        'canFail': False
        },
    'nsIDOMDocument_GetElementsByTagNameNS': {
        'thisType': 'nsDocument',
        'code': '    nsRefPtr<nsContentList> result ='
                'self->GetElementsByTagNameNS(arg0, arg1);',
        'canFail': False
        },
    'nsIDOMElement_': {
        'thisType': 'nsGenericElement'
        },
    'nsIDOMElement_GetTagName': {
        'thisType': 'nsGenericElement',
        'code': 'nsString result = self->NodeName();',
        'canFail': False
        },
    'nsIDOMDocument_CreateElement': {
        'thisType': 'nsDocument',
        'code': '    nsCOMPtr<nsIContent> result;\n'
                '    rv = self->CreateElement(arg0, getter_AddRefs(result));'
    },
    'nsIDOMDocument_CreateElementNS': {
        'thisType': 'nsDocument',
        'code': '    nsCOMPtr<nsIContent> result;\n'
                '    rv = self->CreateElementNS(arg0, arg1, getter_AddRefs(result));'
    },
    'nsIDOMDocument_CreateTextNode': {
        'thisType': 'nsDocument',
        'code': '    nsCOMPtr<nsIContent> result;\n'
                '    rv = self->CreateTextNode(arg0, getter_AddRefs(result));'
    },
    'nsIDOMDocument_GetOnreadystatechange' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMDocument_SetOnreadystatechange' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMDocument_GetOnmouseenter' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMDocument_SetOnmouseenter' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMDocument_GetOnmouseleave' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMDocument_SetOnmouseleave' : {
        'thisType' : 'nsDocument',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMElement_GetOnmouseenter' : {
        'thisType' : 'nsGenericElement',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMElement_SetOnmouseenter' : {
        'thisType' : 'nsGenericElement',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMElement_GetOnmouseleave' : {
        'thisType' : 'nsGenericElement',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMElement_SetOnmouseleave' : {
        'thisType' : 'nsGenericElement',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMWindow_GetOnmouseenter' : {
        'thisType' : 'nsIDOMWindow',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMWindow_SetOnmouseenter' : {
        'thisType' : 'nsIDOMWindow',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMWindow_GetOnmouseleave' : {
        'thisType' : 'nsIDOMWindow',
        'unwrapThisFailureFatal' : False
        },
    'nsIDOMWindow_SetOnmouseleave' : {
        'thisType' : 'nsIDOMWindow',
        'unwrapThisFailureFatal' : False
        },
    # WebGL
    'nsIDOMWebGLRenderingContext_TexImage2D': CUSTOM_QS,
    'nsIDOMWebGLRenderingContext_TexSubImage2D': CUSTOM_QS,
    # Canvas 2D
    'nsIDOMCanvasRenderingContext2D_CreateImageData': CUSTOM_QS,
    'nsIDOMCanvasRenderingContext2D_PutImageData': CUSTOM_QS,
    # Nasty hack to make the ordering of |arc| and |arcTo| correct.
    # |arc| is not traceable because it has an optional argument.
    'nsIDOMCanvasRenderingContext2D_ArcTo' : { 'traceable' : False },

    'nsIDOMImageData_GetWidth': {
        'thisType': 'nsIDOMImageData',
        'code': 'uint32_t result = static_cast<mozilla::dom::ImageData*>(self)->GetWidth();',
        'canFail': False
        },
    'nsIDOMImageData_GetHeight': {
        'thisType': 'nsIDOMImageData',
        'code': 'uint32_t result = static_cast<mozilla::dom::ImageData*>(self)->GetHeight();',
        'canFail': False
        },
    'nsIDOMImageData_GetData': {
        'canFail': False
        }
    }

